
// proxy实现私有变量

class Point{
    constructor(x,y){
        class Point{
            constructor(x,y){
                this._x = x
                this._y = y
                this.notPrivate = 'notPrivate'
            }
            get x(){
                return this._x
            }
            set x(x){
                this._x = x
            }
            _privateFun(){
                console.log('这个是私有方法，直接调用会报错')
            }
            get privateFun(){
                return this._privateFun()
            }
        }
        // 重新设置原型链指向
        var instance = new Proxy( new Point(...arguments),handlerPrivate)
        Object.setPrototypeOf(Object.getPrototypeOf(instance), this)
        return instance
    }
}
// 处理属性私有化
const handlerPrivate = {
    get: function(target, key) {
        if (key[0] === '_') {
            throw new Error('Attempt to access private property');
        }else if (key === 'toJSON') {
            // JSON.stringify 时还是会有问题，因为它会尝试将私有属性序列化成字符串。
            // 为了避免这个问题，我们需要重载 toJSON 函数来返回“公有”属性
            const obj = {};
            for (const key in target) {
                if (key[0] !== '_') { // Only copy over the public properties
                    obj[key] = target[key]
                }
            }
            return () => obj
        }
        return target[key]
    },
    set: function(target, key, value) {
        if (key[0] === '_') {
            throw new Error('Attempt to access private property');
        }
        target[key] = value
    },
    // 禁止私有属性枚举出来
    getOwnPropertyDescriptor(target, key) {
        const desc = Object.getOwnPropertyDescriptor(target, key)
        if (key[0] === '_') {
            desc.enumerable = false;
        }
        return desc
    }
}



const point = new Point(10,20)
console.log(point instanceof Point) // true
for(const key in point){  // 私有属性不可枚举
    console.log(key)  // notPrivate
}
console.log(JSON.stringify(point)); // {"notPrivate":"notPrivate"}
console.log(point.x) // 10
point.x = 20
console.log(point.x) // 20
//console.log(point._x) // 10 //Error: Attempt to access private property at Object.get
// point._x = 20  //Error: Attempt to access private property at Object.set


